package com.quanyan.club.pullclub.service.impl;

import com.alibaba.dubbo.common.utils.CollectionUtils;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Maps;
import com.quanyan.api.APIResponse;
import com.quanyan.club.constants.ClubConstants;
import com.quanyan.club.entity.db.*;
import com.quanyan.club.mapper.*;
import com.quanyan.club.pullclub.entity.req.*;
import com.quanyan.club.pullclub.entity.resp.*;
import com.quanyan.club.pullclub.service.PullClubService;
import com.quanyan.club.pullclub.service.PullClubSupportService;
import com.quanyan.common.Plugin.PageObj;
import com.quanyan.common.constants.Constants;
import com.quanyan.common.exception.BizException;
import com.quanyan.common.utils.CommonUtils;
import com.quanyan.common.utils.DateUtils;
import com.quanyan.common.utils.Limit;
import com.quanyan.orderpay.request.ReqWithdrawApply;
import com.quanyan.orderpay.request.WithdrawPayInfo;
import com.quanyan.orderpay.response.mq.WithdrawTransferNotify;
import com.quanyan.orderpay.service.OrderPayService;
import com.quanyan.user.response.RespUserInfoDetail;
import com.quanyan.user.serviceFacade.UserServiceFacade;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.util.*;

/**
 * Created by yue.yuan on 2017/2/13.
 */
@Service("pullClubService")
public class PullClubServiceImpl implements PullClubService {

    private static Logger logger = LoggerFactory.getLogger(PullClubServiceImpl.class);

    @Autowired
    private TbChannelUserMapper channelUserMapper;
    @Autowired
    private TbClubMapper clubMapper;
    @Autowired
    private TbChannelStreamMapper tbChannelStreamMapper;
    @Autowired
    private OrderPayService orderPayService;
    @Autowired
    private TbChannelUserMapper tbChannelUserMapper;
    @Autowired
    private TbChannelSellMapper tbChannelSellMapper;
    @Autowired
    private TbClubMapper tbClubMapper;
    @Autowired
    private UserServiceFacade userServiceFacade;
    @Autowired
    private TbChannelMapper tbChannelMapper;
    @Autowired
    private PullClubSupportService pullClubSupportService;
    @Autowired
    private PullClubMapper pullClubMapper;

    @Override
    public RespMyNewClubOfPullPage getPullNewClubsByUid(int uid, int pageNo, int pageSize) {

        logger.warn("------my new club page: old club uid=" + uid);
        RespMyNewClubOfPullPage page = new RespMyNewClubOfPullPage();
        TbChannelUserExample channelUserExample = new TbChannelUserExample();
        channelUserExample.createCriteria()
                .andTypeEqualTo((byte) 2)        //老带新
                .andOldClubUidEqualTo(uid)
                .andClubIdNotEqualTo(0)
                .andStatusGreaterThanOrEqualTo((byte)2);
        List<TbChannelUser> channelUserList = channelUserMapper.selectByExample(channelUserExample);

        channelUserExample.setLimit(Limit.buildLimit(pageNo==0?1:pageNo, pageSize));

        List<TbChannelUser> channelUsers = channelUserMapper.selectByExample(channelUserExample);
        if (channelUsers == null || channelUsers.size() == 0) {
            return page;
        }

        int count = channelUserMapper.countByExample(channelUserExample);

        page.setNewClubCount(channelUserList.size());

        List<RespPullNewClub> pullNewClubs = new ArrayList<>();
        for (TbChannelUser channelUser : channelUsers) {
            RespPullNewClub newClub = new RespPullNewClub();
            newClub.setOldUid(channelUser.getOldClubUid());
            int newClubId = channelUser.getClubId();
            TbClub tbClub = clubMapper.selectByPrimaryKey(newClubId);
            if (tbClub != null) {
                newClub.setNewClubId(newClubId);
                newClub.setNewClubName(tbClub.getClubName());
                newClub.setAwardEggs(channelUser.getClubAwardEgg());
                newClub.setFinishActivityCount(channelUser.getClubActivityCount());
                newClub.setFinishActivityTargetCount(3);
                newClub.setUsableDrawPrizeCount(channelUser.getDrawCount());
                pullNewClubs.add(newClub);
            }
        }

        int gotAwardClubCount = 0;
        int oldClubAwardTotalEggs = 0;
        for (TbChannelUser channelUser : channelUserList) {
            Integer oldGotEggs = channelUser.getOldClubAwardEgg();     //老俱乐获取的鸟蛋奖励数
            if (oldGotEggs != null && oldGotEggs != 0) {
                oldClubAwardTotalEggs += oldGotEggs;
                gotAwardClubCount++;       //老俱乐部获得了奖励，新俱乐部一定获得了奖励
            }
        }
        page.setGotAwardClubCount(gotAwardClubCount);
        page.setTotalEggs(oldClubAwardTotalEggs);
        page.setPullNewClubList(PageObj.create(count, pageNo, pageSize, pullNewClubs));

        return page;
    }

    @Override
    public APIResponse<PageObj<List<RespIncomeDetail>>> queryIncomeDetail(ReqIncomeDetail reqIncomeDetail) {

        Integer roleId = pullClubSupportService.getRoleIdByCode(reqIncomeDetail.getRoleType(),
                reqIncomeDetail.getCode(), null);
        if (null == roleId || roleId == 0) {
            return APIResponse.returnFail("当前用户不可用");
        }
        List<RespIncomeDetail> respIncomeLists = new ArrayList<RespIncomeDetail>();
        TbChannelStreamExample tbChannelStreamExample = new TbChannelStreamExample();
        tbChannelStreamExample.createCriteria().andRoleIdEqualTo(roleId)
                .andRoleTypeEqualTo(reqIncomeDetail.getRoleType())
                .andTypeEqualTo(Constants.BYTE_ZERO);
        int total = tbChannelStreamMapper.countByExample(tbChannelStreamExample);
        if (total <= 0) {
            return APIResponse.returnSuccess(PageObj.create(0, reqIncomeDetail.getPageNo(),
                    reqIncomeDetail.getPageSize(), respIncomeLists));
        }
        tbChannelStreamExample.setLimit(Limit.buildLimit(reqIncomeDetail.getPageNo(),
                reqIncomeDetail.getPageSize()));
        tbChannelStreamExample.setOrderByClause("id desc");
        List<TbChannelStream> tbChannelStreams =
                tbChannelStreamMapper.selectByExample(tbChannelStreamExample);
        if (CollectionUtils.isEmpty(tbChannelStreams)) {
            return APIResponse.returnSuccess(PageObj.create(0, reqIncomeDetail.getPageNo(),
                    reqIncomeDetail.getPageSize(), respIncomeLists));
        }
        convertIncomes(tbChannelStreams, respIncomeLists);
        return APIResponse.returnSuccess(PageObj.create(total, reqIncomeDetail.getPageNo(),
                reqIncomeDetail.getPageSize(), respIncomeLists));
    }


    public APIResponse preWithdrawApply(ReqIncomeDetail reqIncomeDetail) {
        int roleType = reqIncomeDetail.getRoleType();
        String code = reqIncomeDetail.getCode();
        Integer roleId = pullClubSupportService.getRoleIdByCode(roleType, code, null);
        if(null == roleId || roleId <= 0) {
            return APIResponse.returnFail("当前用户不可用");
        }
        ChannelSellDo model = pullClubSupportService.getChannelSellModel(roleId, roleType);
        if(null == model) {
            return APIResponse.returnFail("当前用户不存在");
        }
        RespUserAccount respUserAccount = new RespUserAccount();
        respUserAccount.setAccountName(model.getAccountName());
        respUserAccount.setIsBind((int)model.getIsBind());
        respUserAccount.setAccount(model.getAccount());
        respUserAccount.setUsableMoney(model.getUsableMoney());
        convertWithdrawSetting(respUserAccount);
        int count = todayWithdrawCount(roleId, (byte)roleType);
        respUserAccount.setCounts(respUserAccount.getCounts() - count);
        return APIResponse.returnSuccess(respUserAccount);
    }

    @Override
    public APIResponse queryIncomeTotal(ReqIncomeDetail reqIncomeDetail) {
        int roleType = reqIncomeDetail.getRoleType();
        Integer roleId = pullClubSupportService.getRoleIdByCode(roleType, reqIncomeDetail.getCode(), null);
        if(null == roleId || roleId <= 0) {
            return APIResponse.returnFail("当前用户不可用");
        }
        ChannelSellDo channelSellDo = pullClubSupportService.getChannelSellModel(roleId, roleType);
        if(null == channelSellDo) {
            return APIResponse.returnFail("当前用户不存在");
        }
        int pageNo = reqIncomeDetail.getPageNo();
        int pageSize = reqIncomeDetail.getPageSize();
        RespIncomeTotal respIncomeTotal = new RespIncomeTotal();
        List<PullWithdrawDetail> pullWithdrawDetails = new ArrayList<PullWithdrawDetail>();
        List<RespChannelIncomes> incomes = pullClubMapper.selectSellByIncome(
                Arrays.asList(roleId), reqIncomeDetail.getRoleType());
        if(CollectionUtils.isEmpty(incomes)) {
            respIncomeTotal.setUsableMoney(BigDecimal.ZERO);
            respIncomeTotal.setTotalIncome(BigDecimal.ZERO);
        } else {
            RespChannelIncomes respChannelIncomes = incomes.get(0);
            respIncomeTotal.setTotalIncome(respChannelIncomes.getSumIncome());
            respIncomeTotal.setUsableMoney(channelSellDo.getUsableMoney());
        }
        respIncomeTotal.setIsBind((int)channelSellDo.getIsBind());
        PageObj<List<PullWithdrawDetail>> pageObj = null;
        pageObj = queryPullWithdrawDetails(roleId, (byte)roleType, pageNo, pageSize);
        respIncomeTotal.setPullWithdrawDetailList(pageObj);
        Map<String, Object> map = pullClubSupportService.getPointBy(ClubConstants.PULL_WITHDRAW_SETTING);
        convertWithdrawSetting(respIncomeTotal);
        int count = todayWithdrawCount(roleId, (byte)roleType);
        respIncomeTotal.setCounts(respIncomeTotal.getCounts() - count);
        return APIResponse.returnSuccess(respIncomeTotal);
    }

    @Override
    public APIResponse bindingAccount(ReqPullBind reqPullBind) {
        String code = reqPullBind.getCode();
        int roleType = reqPullBind.getRoleType();
        int type = reqPullBind.getType();
        String account = type == 1 ? reqPullBind.getAccount() : null;
        String accountName = type == 1 ? reqPullBind.getAccountName() : null;
        Byte accountType = type == 1 ? reqPullBind.getAccountType() : null;
        String mobile = reqPullBind.getMobile();
        if (roleType == 1) {
            TbChannelSellExample tbChannelSellExample = new TbChannelSellExample();
            tbChannelSellExample.createCriteria().andCodeEqualTo(code)
                    .andIsDeleteEqualTo(Constants.BYTE_ZERO);
            List<TbChannelSell> tbChannelSells =
                    tbChannelSellMapper.selectByExample(tbChannelSellExample);
            if (null == tbChannelSells || tbChannelSells.size() != 1) {
                return APIResponse.returnFail("不存在当前账号或已停用");
            }
            TbChannelSell tbChannelSell = tbChannelSells.get(0);
            if (type == 1 && !mobile.equals(tbChannelSell.getSellMobile())) {
                return APIResponse.returnFail("手机号不匹配");
            }
            if (tbChannelSell.getIsBind().intValue() == reqPullBind.getType()) {
                return APIResponse.returnFail("已经绑定/解绑账户了");
            }
            tbChannelSell.setIsBind((byte)type);
            tbChannelSell.setAccount(account);
            tbChannelSell.setAccountName(accountName);
            tbChannelSell.setAccountType(accountType);
            tbChannelSellMapper.updateByPrimaryKey(tbChannelSell);
            return APIResponse.returnSuccess("绑定/解绑成功！");
        } else if (roleType == 0) {
            TbChannelExample tbChannelExample = new TbChannelExample();
            tbChannelExample.createCriteria().andSellCodeEqualTo(code)
                    .andIsDeleteEqualTo(Constants.BYTE_ZERO);
            List<TbChannel> tbChannels = tbChannelMapper.selectByExample(tbChannelExample);
            if (null == tbChannels || tbChannels.size() != 1) {
                return APIResponse.returnFail("不存在当前账号或已停用");
            }
            TbChannel tbChannel = tbChannels.get(0);
            if (type == 1 && !mobile.equals(tbChannel.getChMobile())) {
                return APIResponse.returnFail("手机号不匹配");
            }
            if (tbChannel.getIsBind().intValue() == type) {
                return APIResponse.returnFail("已经绑定/解绑账户了");
            }
            tbChannel.setIsBind((byte)type);
            tbChannel.setAccount(account);
            tbChannel.setAccountName(accountName);
            tbChannel.setAccountType(accountType);
            tbChannelMapper.updateByPrimaryKey(tbChannel);
            return APIResponse.returnSuccess("绑定/解绑成功！");
        }
        return APIResponse.returnFail("用户类型不存在");
    }


    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public APIResponse withdrawApply(HttpServletRequest request,
                                     ReqPullWithdrawApply reqPullWithdrawApply) {
        int roleType = reqPullWithdrawApply.getRoleType();
        String code = reqPullWithdrawApply.getCode();
        Integer roleId = pullClubSupportService.getRoleIdByCode(roleType, code, null);
        if(null == roleId || roleId <= 0) {
            return APIResponse.returnFail("当前用户不可用");
        }
        ChannelSellDo model = pullClubSupportService.getChannelSellModel(roleId, roleType);
        if(null == model) {
            return APIResponse.returnFail("当前用户不存在");
        }
        APIResponse valid = validWithdrawApply(roleId, reqPullWithdrawApply,
                model.getUsableMoney());
        if(!valid.isRet()) {
            return valid;
        }
        BigDecimal applyMoney = reqPullWithdrawApply.getApplyMoney();
        ReqWithdrawApply reqWithdrawApply = new ReqWithdrawApply();
        reqWithdrawApply.setSourceSystemCode(Constants.CLUB_SYSTEM_CODE);
        reqWithdrawApply.setSourceBusinessCode(Constants.CLUB_CHANNEL_WITHDRAW_BUSINESS_CODE);
        String serialNo = CommonUtils.generateBusinessOrderNo(Constants.CLUB_SYSTEM, roleId);
        WithdrawPayInfo withdrawPayInfo = new WithdrawPayInfo();
        String account = model.getAccount();
        String accountName = model.getAccountName();
        String mobile = model.getMobile();
        Integer payType = model.getAccountType() + 1;
        convertWithdrawPayInfo(serialNo, account,accountName, applyMoney,
                BigDecimal.ZERO, mobile, withdrawPayInfo);
        reqWithdrawApply.setPayType(payType);
        reqWithdrawApply.setWithdrawPayInfo(withdrawPayInfo);
        String serverUrl = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort();
        reqWithdrawApply.setNotifyUrl(serverUrl + "/api/club/callBack/pull/withdrawNotify");
        reqWithdrawApply.setAppVersion(request.getHeader("APPVersion"));
        //插入提现流水
        TbChannelStream tbChannelStream = pullClubSupportService.insertChannelStream(null,
                serialNo, 0, applyMoney, 0, model, Constants.BYTE_TWO, Constants.BYTE_ZERO, null);
        if(roleType == Constants.BYTE_ZERO) {
            TbChannel update = new TbChannel();
            update.setId(model.getId());
            update.setUsableMoney(model.getUsableMoney().subtract(applyMoney));
            update.setFreezeMoney(model.getFreezeMoney().add(applyMoney));
            tbChannelMapper.updateByPrimaryKeySelective(update);
        } else {
            TbChannelSell update = new TbChannelSell();
            update.setId(model.getId());
            update.setUsableMoney(model.getUsableMoney().subtract(applyMoney));
            update.setFreezeMoney(model.getFreezeMoney().add(applyMoney));
            tbChannelSellMapper.updateByPrimaryKeySelective(update);
        }
        logger.warn("---withdraw req---" + JSONObject.toJSONString(reqWithdrawApply));
        APIResponse apiResponse = orderPayService.applyWithdraw(reqWithdrawApply);
        if (apiResponse == null || !apiResponse.isRet()) {
            logger.error("向支付系统提交提现申请失败，{}" + JSONObject.toJSONString(apiResponse));
            throw new BizException(apiResponse.getErrmsg());
        } else {
            //记录支付系统返回的提现申请流水号
            Integer withdrawNo = Integer.parseInt(String.valueOf(apiResponse.getData()));
            TbChannelStream updateStream = new TbChannelStream();
            updateStream.setId(tbChannelStream.getId());
            updateStream.setWithdrawNo(withdrawNo);
            tbChannelStreamMapper.updateByPrimaryKeySelective(updateStream);
        }
        return APIResponse.returnSuccess(serialNo);
    }

    public APIResponse withdrawSource(ReqWithdrawSource reqIncomeDetail) {
        Integer withdrawNo = reqIncomeDetail.getWithdrawNo();
        if(null == withdrawNo || withdrawNo <= 0) {
            return APIResponse.returnFail("没有这个提现号");
        }
        TbChannelStreamExample example = new TbChannelStreamExample();
        TbChannelStreamExample.Criteria criteria = example.createCriteria();
        criteria.andWithdrawNoEqualTo(withdrawNo);
        List<TbChannelStream> streams = tbChannelStreamMapper.selectByExample(example);
        if(CollectionUtils.isEmpty(streams)) {
            return  APIResponse.returnFail("没有这条提现记录");
        }
        List<RespIncomeDetail> respIncomeLists = new ArrayList<RespIncomeDetail>();
        TbChannelStream tbChannelStream = streams.get(0);
        int roleId = tbChannelStream.getRoleId();
        byte roleType = tbChannelStream.getRoleType();
        example.clear();
        criteria = example.createCriteria();
        criteria.andRoleTypeEqualTo(roleType)
                .andRoleIdEqualTo(roleId).andStatusEqualTo(Constants.BYTE_ONE)
                .andTypeEqualTo(Constants.BYTE_ONE);
        example.setOrderByClause(" id desc ");
        example.setLimit(Limit.buildLimit(0,1));
        List<TbChannelStream> channelStreams =
                tbChannelStreamMapper.selectByExample(example);
        Date leastWithdrawSuccess = null;
        if(CollectionUtils.isNotEmpty(channelStreams)) {
            leastWithdrawSuccess = channelStreams.get(0).getCreateTime();
        }
        example.clear();
        criteria = example.createCriteria().andRoleIdEqualTo(roleId)
                .andRoleTypeEqualTo(roleType)
                .andTypeEqualTo(Constants.BYTE_ZERO);
        if(null != leastWithdrawSuccess) {
            criteria.andCreateTimeGreaterThan(leastWithdrawSuccess);
        }
        int total = tbChannelStreamMapper.countByExample(example);
        if (total <= 0) {
            return APIResponse.returnSuccess(PageObj.create(0, reqIncomeDetail.getPageNo(),
                    reqIncomeDetail.getPageSize(), respIncomeLists));
        }
        example.setLimit(Limit.buildLimit(reqIncomeDetail.getPageNo(),
                reqIncomeDetail.getPageSize()));
        example.setOrderByClause("id desc");
        List<TbChannelStream> tbChannelStreams =
                tbChannelStreamMapper.selectByExample(example);
        if (CollectionUtils.isEmpty(tbChannelStreams)) {
            return APIResponse.returnSuccess(PageObj.create(0, reqIncomeDetail.getPageNo(),
                    reqIncomeDetail.getPageSize(), respIncomeLists));
        }
        convertIncomes(tbChannelStreams, respIncomeLists);
        return APIResponse.returnSuccess(PageObj.create(total, reqIncomeDetail.getPageNo(),
                reqIncomeDetail.getPageSize(), respIncomeLists));
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public APIResponse withdrawCallbackNotify(WithdrawTransferNotify notify) {

        //1. 过滤，只处理本系统的提现业务
        String systemCode = notify.getSourceSystemCode();
        String bussinessCode = notify.getSourceBusinessCode();
        if (!systemCode.equals(Constants.CLUB_SYSTEM_CODE) ||
                !bussinessCode.equals(Constants.CLUB_CHANNEL_WITHDRAW_BUSINESS_CODE)) {
            logger.warn("非俱乐部提现");
            return APIResponse.returnSuccess();
        }

        Integer withdrawNo = null;
        withdrawNo = Integer.parseInt(notify.getWithdrawNo()); //支付系统生成的提现申请流水号
        String serialNo = notify.getApplyNo() + withdrawNo; // 提现成功流水号=申请流水号+提现号
        //2. 查询出此条俱乐部提现申请
        TbChannelStreamExample example = new TbChannelStreamExample();
        TbChannelStreamExample.Criteria criteria = example.createCriteria();
        criteria
                .andWithdrawNoEqualTo(Integer.valueOf(withdrawNo))
                .andStatusEqualTo(Constants.BYTE_ONE)
                .andIsDeleteEqualTo(Constants.IS_DELETE_FALSE);
        if (tbChannelStreamMapper.countByExample(example) > 0){  //已经提现成功了，再次回调，跳过
            return APIResponse.returnSuccess();
        }
        example.clear();
        criteria = example.createCriteria();
        criteria
                .andWithdrawNoEqualTo(withdrawNo)
                .andIsDeleteEqualTo(Constants.IS_DELETE_FALSE);
        //支付系统状态成功
        if (notify.getTag()){
            criteria.andStatusNotEqualTo(Constants.BYTE_ONE);        //公司已付款，提现已成功，不能再次更新俱乐部线上资金
        }else {
            criteria.andStatusNotEqualTo((byte)3);       //已经失败了，再次回调，不再恢复冻结资金
        }
        List<TbChannelStream> tbChannelStreams = tbChannelStreamMapper.selectByExample(example);
        if (tbChannelStreams == null || tbChannelStreams.isEmpty()) {
            return APIResponse.returnFail("提现回调直接返回：可能原因，1. 提现流水号{}不存在，2. 或者公司已付款，提现已成功，重复的回调，3. 或已更新提现失败状态，再次回调不再次恢复冻结资金" + withdrawNo);
        }
        TbChannelStream tbChannelStream = tbChannelStreams.get(0);

        String reason = notify.getReason();     //付款成功或失败原因
        if(null == reason) {
            reason = "";
        }
        BigDecimal amount = notify.getAmount(); //提现金额，返回的单位为: 元
        amount = amount.setScale(2, BigDecimal.ROUND_HALF_UP);
        TbChannelStream update = new TbChannelStream();
        ChannelSellDo model = pullClubSupportService.getChannelSellModel(tbChannelStream.getRoleId(),
                tbChannelStream.getRoleType());
        if(null == model) {
            return APIResponse.returnFail("当前用户不存在");
        }
        model.setAccount(tbChannelStream.getWithdrawAccount());
        if (notify.getTag()) {      //如果付款成功
            Map<String, Object> map = new HashMap<>();
            map.put("withdrawAmount", amount.doubleValue());
            logger.warn("提现金额：" + map);

            TbChannelStream channelStream = pullClubSupportService.insertChannelStream(withdrawNo, serialNo, 0,
                    tbChannelStream.getOutput(), 0, model, Constants.BYTE_ONE,
                    Constants.BYTE_ONE, null);
            if (channelStream == null) {
                logger.error("俱乐部渠道提现回调，扣除俱乐部渠道{}线上金额失败。", withdrawNo);
                reason += "俱乐部提现回调，扣除线上金额失败";
                //处理失败
                notify.setTag(false);  //更新资金失败
            }
            else {
                 //处理成功，记录流水
                logger.warn("提现到账成功：" + JSON.toJSONString(notify));

            }
        }else {
            //恢复冻结资金
            logger.warn("提现回调参数：{}", JSON.toJSON(notify));
            logger.warn("解冻资金===========》");
            int updateRet = 0;
            if(tbChannelStream.getRoleType().equals(Constants.BYTE_ONE)) {
                TbChannelSell updateModel = new TbChannelSell();
                updateModel.setId(model.getId());
                updateModel.setFreezeMoney(model.getFreezeMoney().
                        subtract(tbChannelStream.getOutput()));
                updateModel.setUsableMoney(model.getUsableMoney().add(tbChannelStream.getOutput()));
                updateRet = tbChannelSellMapper.updateByPrimaryKeySelective(updateModel);
            } else if(tbChannelStream.getRoleType().equals(Constants.BYTE_ZERO)) {
                TbChannel updateModel = new TbChannel();
                updateModel.setId(model.getId());
                updateModel.setFreezeMoney(model.getFreezeMoney().
                        subtract(tbChannelStream.getOutput()));
                updateModel.setUsableMoney(model.getUsableMoney().add(tbChannelStream.getOutput()));
                updateRet = tbChannelMapper.updateByPrimaryKeySelective(updateModel);
            }
            if (updateRet != 1) {
                logger.error("俱乐部提现回调，解冻俱乐部{}线上金额失败。", withdrawNo);
                reason += "俱乐部提现回调，解冻线上金额失败";
            }
            TbChannelStream channelStream = pullClubSupportService.insertChannelStream(
                    withdrawNo,serialNo, 0, tbChannelStream.getOutput(), 0,
                    model, Constants.BYTE_ONE, (byte)3, reason);

        }

        return APIResponse.returnSuccess();
    }

    private APIResponse validWithdrawApply(int roleId, ReqPullWithdrawApply reqPullWithdrawApply,
                                           BigDecimal usableMoney) {
        BigDecimal money = reqPullWithdrawApply.getApplyMoney();
        int roleType = reqPullWithdrawApply.getRoleType();
        //金额校验
        BigDecimal limitMoney = BigDecimal.ZERO;
        BigDecimal lowestMoney = BigDecimal.ZERO;
        Map<String, Object> map = pullClubSupportService.getPointBy(ClubConstants.PULL_WITHDRAW_SETTING);
        List<Integer> grades= (List<Integer>) map.get(ClubConstants.RULE_SETTING_PULL_GRADE);
        BigDecimal withdrawMoney = BigDecimal.ZERO;
        if(CollectionUtils.isNotEmpty(grades)) {
            lowestMoney = new BigDecimal(grades.get(0));
        }
        List<Integer> points= (List<Integer>) map.get(ClubConstants.RULE_SETTING_PULL_POINT);
        if(CollectionUtils.isNotEmpty(points)) {
            limitMoney = new BigDecimal(points.get(0));
        }
        Double limitCounts = (double)map.get(ClubConstants.RULE_SETTING_PULL_RATE);
        if(money.compareTo(limitMoney) == 1 || money.compareTo(lowestMoney) == -1) {
            return APIResponse.returnFail("申请提现金额不合法，应在"+ lowestMoney + "-"
                    + limitMoney + "之间");
        }
        if(usableMoney.compareTo(limitMoney) == 1) {
            usableMoney = limitMoney;
        }
        if(usableMoney.compareTo(money) != 0) {
            return APIResponse.returnFail("可提现金额与申请提现金额不相符");
        }
        int limitCount = new BigDecimal(limitCounts).intValue();
        int count = todayWithdrawCount(roleId, (byte)roleType);
        if(count >= limitCount) {
            return APIResponse.returnFail("提现次数超过最大可提现次数，最大次数：" + limitCount);
        }
        return APIResponse.returnSuccess();
    }

    private int todayWithdrawCount(int roleId, byte roleType){
        TbChannelStreamExample example = new TbChannelStreamExample();
        example.createCriteria().andRoleIdEqualTo(roleId).andRoleTypeEqualTo(roleType)
                .andTypeEqualTo(Constants.BYTE_TWO)
                .andCreateTimeBetween(DateUtils.getTimesmorning(),DateUtils.getTimesnight());
        int count = tbChannelStreamMapper.countByExample(example);
        return count;
    }

    private void convertWithdrawPayInfo(String serialNo, String account, String accountName,
                                               BigDecimal applyMoney, BigDecimal balance,
                                               String mobile, WithdrawPayInfo withdrawPayInfo) {
        withdrawPayInfo.setApplyNo(serialNo);//流水号
        withdrawPayInfo.setAccountNo(account);
        withdrawPayInfo.setName(accountName);
        withdrawPayInfo.setAmount(applyMoney);
        withdrawPayInfo.setPhone(mobile);//mobile
        withdrawPayInfo.setBalance(balance);
        withdrawPayInfo.setApplyTime(new Date());
        withdrawPayInfo.setWithdrawDesc("渠道资金提现");
    }

    private PageObj<List<PullWithdrawDetail>> queryPullWithdrawDetails(int roleId, byte roleType,
                                                                       Integer pageNo, Integer pageSize) {
        List<PullWithdrawDetail> pullWithdrawDetails = new ArrayList<PullWithdrawDetail>();
        int total = pullClubMapper.countWithdrawDetails(roleId, roleType);
        if(total <= 0) {
            return PageObj.create(total, pageNo, pageSize, pullWithdrawDetails);
        }
        Limit limit = Limit.buildLimit(pageNo, pageSize);
        List<TbChannelStream> channelStreams = pullClubMapper.selectWithdrawDetails(roleId,
                roleType, limit.getStart(), limit.getSize());
        if(CollectionUtils.isEmpty(channelStreams)) {
            return PageObj.create(total, pageNo, pageSize, pullWithdrawDetails);
        }
        for(TbChannelStream tbChannelStream : channelStreams) {
            PullWithdrawDetail pullWithdrawDetail = new PullWithdrawDetail();
            if(null == tbChannelStream) {
                continue;
            }
            pullWithdrawDetail.setCreateTime(tbChannelStream.getCreateTime());
            pullWithdrawDetail.setOutput(tbChannelStream.getOutput());
            if(null == tbChannelStream.getPayChannel()) {
                pullWithdrawDetail.setPayChannel(0);
            } else {
                pullWithdrawDetail.setPayChannel((int)tbChannelStream.getPayChannel());
            }
            pullWithdrawDetail.setUserAccount(tbChannelStream.getWithdrawAccount());
            pullWithdrawDetail.setRemark(tbChannelStream.getRemark());
            pullWithdrawDetail.setSerialNo(tbChannelStream.getSerialNo());
            pullWithdrawDetail.setStatus((int)tbChannelStream.getStatus());
            pullWithdrawDetails.add(pullWithdrawDetail);
        }
        return PageObj.create(total, pageNo, pageSize, pullWithdrawDetails);
    }

    private void convertIncomes(List<TbChannelStream> tbChannelStreams,
                                List<RespIncomeDetail> respIncomeLists) {
        List<Integer> userIds = new ArrayList<Integer>();
        for (TbChannelStream tbChannelStream : tbChannelStreams) {
            if(!userIds.contains(tbChannelStream.getChUserId())) {
                userIds.add(tbChannelStream.getChUserId());
            }
        }
        APIResponse<List<RespUserInfoDetail>> respUserInfoBase = null;
        List<RespUserInfoDetail> respUserInfoBases = new ArrayList<RespUserInfoDetail>();
        respUserInfoBase = userServiceFacade.batchQueryUserInfoDetail(userIds);
        if (respUserInfoBase.isRet()) {
            respUserInfoBases = respUserInfoBase.getData();
        }
        Map<Integer, RespUserInfoDetail> userIdAndInfo = Maps.newHashMap();
        for (RespUserInfoDetail userInfo : respUserInfoBases) {
            if (null != userInfo) {
                userIdAndInfo.put(userInfo.getUid(), userInfo);
            }
        }
        for (TbChannelStream tbChannelStream : tbChannelStreams) {
            RespIncomeDetail detail = new RespIncomeDetail();
            RespUserInfoDetail userInfo = userIdAndInfo.get(tbChannelStream.getChUserId());
            if(null == userInfo) {
                logger.warn("用户信息为空...");
                continue;
            }
            detail.setChannelUserMobile(userInfo.getMobile());
            detail.setChannelUserName(userInfo.getNickName());
            TbClub club = tbClubMapper.selectByPrimaryKey(tbChannelStream.getClubId());
            detail.setClubName(club.getClubName());
            detail.setIncome(tbChannelStream.getIncome());
            detail.setIncomeTime(tbChannelStream.getCreateTime());
            TbChannelUserExample example = new TbChannelUserExample();
            example.createCriteria().andUidEqualTo(tbChannelStream.getChUserId());
            List<TbChannelUser> users = tbChannelUserMapper.selectByExample(example);
            if(CollectionUtils.isEmpty(users)) {
                continue;
            }
            TbChannelUser tbChannelUser = users.get(0);
            Integer pullRoleId = pullClubSupportService.getRoleIdByCode(tbChannelUser.getType(),
                    null, tbChannelUser.getCode());
            if(tbChannelUser.getType().equals(Constants.BYTE_ONE)) {
                ChannelSellDo channelSellDo =
                        pullClubSupportService.getChannelSellModel(pullRoleId, tbChannelUser.getType());
                detail.setSellMobile(channelSellDo.getMobile());
                detail.setSellRate(channelSellDo.getSellRate());
            }

            respIncomeLists.add(detail);
        }
    }

    private APIResponse convertWithdrawSetting(RespUserAccount respUserAccount) {
        Map<String, Object> map = pullClubSupportService.getPointBy(ClubConstants.PULL_WITHDRAW_SETTING);
        List<Integer> grades= (List<Integer>) map.get(ClubConstants.RULE_SETTING_PULL_GRADE);
        if(CollectionUtils.isEmpty(grades)) {
            return APIResponse.returnFail("配置不全，提现最低金额未配置");
        }
        respUserAccount.setLowestAmount(new BigDecimal(grades.get(0)));
        Double rate = (Double)map.get(ClubConstants.RULE_SETTING_PULL_RATE);
        if(null == rate) {
            return APIResponse.returnFail("配置不全，提现最高次数未配置");
        }
        BigDecimal limitCount = new BigDecimal(rate);
        respUserAccount.setCounts(limitCount.intValue());
        List<Integer> points= (List<Integer>) map.get(ClubConstants.RULE_SETTING_PULL_POINT);
        if(CollectionUtils.isEmpty(points)) {
            return APIResponse.returnFail("配置不全，提现最高金额未配置");
        }
        respUserAccount.setLimitAmount(new BigDecimal(points.get(0)));
        return APIResponse.returnSuccess();
    }
}
